/*
 * Copyright 2023-2025, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * 龙芯LoongArch64架构稳定计数器定时器实现
 * 本文件实现基于龙芯稳定计数器的定时器功能
 */

#include <KernelExport.h>

#include <timer.h>
#include <arch/timer.h>
#include <boot/kernel_args.h>
#include <kernel.h>
#include <debug.h>
#include <int.h>

#include "loongarch_timer.h"


//#define TRACE_LOONGARCH_TIMER
#ifdef TRACE_LOONGARCH_TIMER
#   define TRACE(x...) dprintf("loongarch_stable_timer: " x)
#else
#   define TRACE(x...) ;
#endif


static bool sLoongArchTimerInitialized = false;

// 全局变量
static uint64 sTimerFrequency = LOONGARCH_STABLE_COUNTER_FREQ;
static uint64 sTimerMax = 0xffffffffffffffffULL;
static uint64 sTimerConversionFactor = 0;


struct timer_info gLoongArchStableTimer = {
	"LoongArch Stable Timer",
	&loongarch_stable_timer_get_prio,
	&loongarch_stable_timer_set_hardware_timer,
	&loongarch_stable_timer_clear_hardware_timer,
	&loongarch_stable_timer_init
};


static int
loongarch_stable_timer_get_prio(void)
{
	// 返回优先级，值越大优先级越高
	return 3;
}


static int32
loongarch_stable_timer_interrupt(void *data)
{
	// 清除定时器中断
	write_csr(CSR_TICLR, 1);
	
	// 调用通用定时器中断处理函数
	return timer_interrupt();
}


static status_t
loongarch_stable_timer_set_hardware_timer(bigtime_t relativeTimeout)
{
	// 将微秒转换为定时器计数值
	uint64 ticks = (static_cast<__uint128_t>(relativeTimeout) * sTimerFrequency) / 1000000;
	
	// 确保不超过最大值
	if (ticks > sTimerMax)
		ticks = sTimerMax;
	
	// 清除定时器中断
	write_csr(CSR_TICLR, 1);
	
	// 设置定时器初值
	write_csr(CSR_TVAL, ticks);
	
	// 配置并启用定时器（单次模式）
	write_csr(CSR_TCFG, TCFG_EN | TCFG_INT_EN);
	
	TRACE("Set hardware timer: %" B_PRId64 " us, ticks: %" B_PRIu64 "\n", 
		relativeTimeout, ticks);
	
	return B_OK;
}


static status_t
loongarch_stable_timer_clear_hardware_timer(void)
{
	// 禁用定时器
	write_csr(CSR_TCFG, 0);
	
	// 清除定时器中断
	write_csr(CSR_TICLR, 1);
	
	TRACE("Cleared hardware timer\n");
	
	return B_OK;
}


static status_t
loongarch_stable_timer_init(struct kernel_args *args)
{
	if (sLoongArchTimerInitialized) {
		TRACE("Timer is already initialized\n");
		return B_OK;
	}

	// 初始化定时器转换因子
	// 这个因子用于将微秒转换为定时器计数值
	sTimerConversionFactor = (1LL << 32) * 1000000LL / LOONGARCH_STABLE_COUNTER_FREQ;

	// 安装定时器中断处理函数
	install_io_interrupt_handler(TIMER_IRQ, &loongarch_stable_timer_interrupt, NULL, 0);
	
	// 禁用定时器，确保干净的初始状态
	loongarch_stable_timer_clear_hardware_timer();

	sLoongArchTimerInitialized = true;
	TRACE("Timer initialized, frequency: %" B_PRIu64 " Hz\n", sTimerFrequency);

	return B_OK;
}